const SystemConfig = require('../models/SystemConfig')
const { ApiError } = require('../utils/error')
const RedisHelper = require('../utils/redisHelper')
const Mailer = require('../utils/mailer')
const SmsService = require('../services/smsService')
const storageService = require('../services/storageService')
const fileService = require('../services/fileService')

const CACHE_KEY = {
  BASIC_CONFIG: 'system:config:basic',
  MAINTENANCE_CONFIG: 'system:config:maintenance',
  MAIL_CONFIG: 'system:config:mail',
  SMS_CONFIG: 'system:config:sms',
  STORAGE_CONFIG: 'system:config:storage'
}

const CACHE_TTL = 3600 // 1小时缓存

// 清除基础配置缓存
const clearBasicConfigCache = async () => {
  await RedisHelper.del(CACHE_KEY.BASIC_CONFIG)
}

// 获取系统维护配置
exports.getMaintenanceConfig = async (req, res) => {
  try {
    let configData
    
    try {
      // 尝试从缓存获取
      const cachedConfig = await RedisHelper.get(CACHE_KEY.MAINTENANCE_CONFIG)
      if (cachedConfig) {
        return res.json({
          code: 0,
          data: cachedConfig
        })
      }
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误时继续从数据库获取
    }

    const config = await SystemConfig.findByPk('maintenance')
    configData = config ? JSON.parse(config.value) : {
      enabled: false,
      message: ''
    }

    try {
      // 尝试设置缓存
      await RedisHelper.set(CACHE_KEY.MAINTENANCE_CONFIG, configData, CACHE_TTL)
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误不影响返回结果
    }

    res.json({
      code: 0,
      data: configData
    })
  } catch (error) {
    console.error('获取系统维护配置失败:', error)
    throw new ApiError(500, '获取系统维护配置失败')
  }
}

// 更新系统维护配置
exports.updateMaintenanceConfig = async (req, res) => {
  const { enabled, message } = req.body

  try {
    await SystemConfig.upsert({
      type: 'maintenance',
      value: JSON.stringify({ enabled, message })
    })

    // 更新缓存
    await RedisHelper.set(CACHE_KEY.MAINTENANCE_CONFIG, { enabled, message }, CACHE_TTL)

    res.json({
      code: 0,
      message: '更新成功'
    })
  } catch (error) {
    throw new ApiError(500, '更新系统维护配置失败')
  }
}

// 获取系统基础配置
exports.getBasicConfig = async (req, res) => {
  try {
    // 尝试从缓存获取
    const cachedConfig = await RedisHelper.get(CACHE_KEY.BASIC_CONFIG)
    if (cachedConfig) {
      return res.json({
        code: 0,
        data: cachedConfig
      })
    }

    const config = await SystemConfig.findByPk('basic')
    const configData = config ? JSON.parse(config.value) : {
      frontendName: '',
      backendName: '',
      logo: '',
      favicon: '',
      loginBackground: '',
      loginLogo: '',
      welcomeText: '',
      footer: ''
    }

    // 设置缓存
    await RedisHelper.set(CACHE_KEY.BASIC_CONFIG, configData, CACHE_TTL)

    res.json({
      code: 0,
      data: configData
    })
  } catch (error) {
    throw new ApiError(500, '获取系统基础配置失败')
  }
}

// 更新系统基础配置
exports.updateBasicConfig = async (req, res) => {
  const {
    frontendName,
    backendName,
    logo,
    favicon,
    loginBackground,
    loginLogo,
    welcomeText,
    footer
  } = req.body

  try {
    const configData = {
      frontendName,
      backendName,
      logo,
      favicon,
      loginBackground,
      loginLogo,
      welcomeText,
      footer
    }

    await SystemConfig.upsert({
      type: 'basic',
      value: JSON.stringify(configData)
    })

    // 清除旧的缓存
    await clearBasicConfigCache()

    res.json({
      code: 0,
      message: '更新成功'
    })
  } catch (error) {
    throw new ApiError(500, '更新系统基础配置失败')
  }
}

// 删除图片
exports.deleteImage = async (req, res) => {
  const { field } = req.body

  try {
    const config = await SystemConfig.findByPk('basic')
    if (!config) {
      throw new ApiError(404, '配置不存在')
    }

    const configData = JSON.parse(config.value)
    configData[field] = ''

    await SystemConfig.upsert({
      type: 'basic',
      value: JSON.stringify(configData)
    })

    // 清除旧的缓存
    await clearBasicConfigCache()

    res.json({
      code: 0,
      message: '删除成功'
    })
  } catch (error) {
    throw new ApiError(500, '删除图片失败')
  }
}

// 获取邮件配置
exports.getMailConfig = async (req, res) => {
  try {
    let configData
    
    try {
      // 尝试从缓存获取
      const cachedConfig = await RedisHelper.get(CACHE_KEY.MAIL_CONFIG)
      if (cachedConfig) {
        return res.json({
          code: 0,
          data: cachedConfig
        })
      }
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误时继续从数据库获取
    }

    const config = await SystemConfig.findByPk('mail')
    configData = config ? JSON.parse(config.value) : {
      mailerHost: '',
      mailerPort: '',
      mailerUser: '',
      mailerPass: '',
      mailerFrom: ''
    }

    try {
      // 尝试设置缓存
      await RedisHelper.set(CACHE_KEY.MAIL_CONFIG, configData, CACHE_TTL)
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误不影响返回结果
    }

    res.json({
      code: 0,
      data: configData
    })
  } catch (error) {
    console.error('获取邮件配置失败:', error)
    throw new ApiError(500, '获取邮件配置失败')
  }
}

// 更新邮件配置
exports.updateMailConfig = async (req, res) => {
  const { mailerHost, mailerPort, mailerUser, mailerPass, mailerFrom } = req.body

  try {
    const configData = {
      mailerHost,
      mailerPort,
      mailerUser,
      mailerPass,
      mailerFrom
    }

    await SystemConfig.upsert({
      type: 'mail',
      value: JSON.stringify(configData)
    })

    // 更新缓存
    await RedisHelper.set(CACHE_KEY.MAIL_CONFIG, configData, CACHE_TTL)

    res.json({
      code: 0,
      message: '更新成功'
    })
  } catch (error) {
    throw new ApiError(500, '更新邮件配置失败')
  }
}

// 测试邮件发送
exports.testMailSend = async (req, res) => {
  try {
    const config = await SystemConfig.findByPk('mail')
    if (!config) {
      throw new ApiError(400, '请先配置邮件服务')
    }

    const mailConfig = JSON.parse(config.value)
    if (!mailConfig.mailerHost || !mailConfig.mailerPort || !mailConfig.mailerUser || !mailConfig.mailerPass) {
      throw new ApiError(400, '邮件配置不完整')
    }

    const mailer = new Mailer(mailConfig)
    await mailer.sendTestMail()

    res.json({
      code: 0,
      message: '测试邮件发送成功'
    })
  } catch (error) {
    throw new ApiError(error.code || 500, error.message || '测试邮件发送失败')
  }
}

// 获取短信配置
exports.getSmsConfig = async (req, res) => {
  try {
    let configData
    
    try {
      // 尝试从缓存获取
      const cachedConfig = await RedisHelper.get(CACHE_KEY.SMS_CONFIG)
      if (cachedConfig) {
        return res.json({
          code: 0,
          data: cachedConfig
        })
      }
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误时继续从数据库获取
    }

    const config = await SystemConfig.findByPk('sms')
    configData = config ? JSON.parse(config.value) : {
      provider: '',
      accessKeyId: '',
      accessKeySecret: '',
      signName: '',
      templateCode: '',
      secretId: '',
      secretKey: '',
      appId: '',
      signContent: '',
      appKey: '',
      appSecret: '',
      channelNumber: '',
      signature: '',
      accessKey: '',
      secretKey: '',
      templateId: ''
    }

    try {
      // 尝试设置缓存
      await RedisHelper.set(CACHE_KEY.SMS_CONFIG, configData, CACHE_TTL)
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误不影响返回结果
    }

    res.json({
      code: 0,
      data: configData
    })
  } catch (error) {
    console.error('获取短信配置失败:', error)
    throw new ApiError(500, '获取短信配置失败')
  }
}

// 更新短信配置
exports.updateSmsConfig = async (req, res) => {
  try {
    const config = req.body
    // 验证配置
    if (!config.provider) {
      throw new ApiError(400, '请选择短信服务商')
    }
    
    // 根据不同服务商验证必填字段
    switch (config.provider) {
      case 'aliyun':
        if (!config.accessKeyId || !config.accessKeySecret || !config.signName || !config.templateCode) {
          throw new ApiError(400, '请填写完整的阿里云配置信息')
        }
        break
      case 'tencent':
        if (!config.secretId || !config.secretKey || !config.appId || !config.signContent || !config.templateId) {
          throw new ApiError(400, '请填写完整的腾讯云配置信息')
        }
        break
      case 'qiniu':
        if (!config.accessKey || !config.secretKey || !config.signature || !config.templateId) {
          throw new ApiError(400, '请填写完整的七牛云配置信息')
        }
        break
      case 'huawei':
        if (!config.appKey || !config.appSecret || !config.channelNumber || !config.signature || !config.templateId) {
          throw new ApiError(400, '请填写完整的华为云配置信息')
        }
        break
      default:
        throw new ApiError(400, '不支持的短信服务商')
    }

    // 保存到数据库
    await SystemConfig.upsert({
      type: 'sms',
      value: JSON.stringify(config)
    })

    // 更新缓存
    await RedisHelper.set(CACHE_KEY.SMS_CONFIG, config, CACHE_TTL)
    
    res.json({
      code: 0,
      message: '保存成功'
    })
  } catch (error) {
    console.error('更新短信配置失败:', error)
    throw error instanceof ApiError ? error : new ApiError(500, '更新短信配置失败')
  }
}

// 测试发送短信
exports.testSmsSend = async (req, res) => {
  try {
    // 从缓存或数据库获取短信配置
    let config = await RedisHelper.get(CACHE_KEY.SMS_CONFIG)
    if (!config) {
      const dbConfig = await SystemConfig.findOne({ where: { type: 'sms' } })
      if (!dbConfig || !dbConfig.value) {
        throw new ApiError(400, '请先配置短信服务')
      }
      config = JSON.parse(dbConfig.value)
      // 更新缓存
      await RedisHelper.set(CACHE_KEY.SMS_CONFIG, config, CACHE_TTL)
    }

    // 验证配置完整性
    if (!config.provider) {
      throw new ApiError(400, '请选择短信服务商')
    }

    // 根据不同服务商验证配置
    switch (config.provider) {
      case 'aliyun':
        if (!config.accessKeyId || !config.accessKeySecret || !config.signName || !config.templateCode) {
          throw new ApiError(400, '请完善阿里云配置信息')
        }
        break
      case 'tencent':
        if (!config.secretId || !config.secretKey || !config.appId || !config.signContent || !config.templateId) {
          throw new ApiError(400, '请完善腾讯云配置信息')
        }
        break
      case 'qiniu':
        if (!config.accessKey || !config.secretKey || !config.signature || !config.templateId) {
          throw new ApiError(400, '请完善七牛云配置信息')
        }
        break
      case 'huawei':
        if (!config.appKey || !config.appSecret || !config.channelNumber || !config.signature || !config.templateId) {
          throw new ApiError(400, '请完善华为云配置信息')
        }
        break
      default:
        throw new ApiError(400, '不支持的短信服务商')
    }

    // 初始化短信服务
    const smsService = new SmsService()
    await smsService.initClient(config)

    // 发送测试短信
    await smsService.sendTestSms()

    res.json({
      code: 0,
      message: '测试短信发送成功'
    })
  } catch (error) {
    console.error('发送测试短信失败:', error)
    throw error instanceof ApiError ? error : new ApiError(500, error.message || '发送测试短信失败')
  }
}

// 获取存储配置
exports.getStorageConfig = async (req, res) => {
  try {
    let configData
    
    try {
      // 尝试从缓存获取
      const cachedConfig = await RedisHelper.get(CACHE_KEY.STORAGE_CONFIG)
      if (cachedConfig) {
        return res.json({
          code: 0,
          data: cachedConfig
        })
      }
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误时继续从数据库获取
    }

    const config = await SystemConfig.findByPk('storage')
    configData = config ? JSON.parse(config.value) : {
      type: 'local',
      provider: '',
      accessKey: '',
      secretKey: '',
      region: '',
      bucket: '',
      domain: '',
      protocol: 'http'
    }

    try {
      // 尝试设置缓存
      await RedisHelper.set(CACHE_KEY.STORAGE_CONFIG, configData, CACHE_TTL)
    } catch (error) {
      console.error('Redis error:', error)
      // Redis 错误不影响返回结果
    }

    res.json({
      code: 0,
      data: configData
    })
  } catch (error) {
    console.error('获取存储配置失败:', error)
    throw new ApiError(500, '获取存储配置失败')
  }
}

// 更新存储配置
exports.updateStorageConfig = async (req, res) => {
  const { type, provider, accessKey, secretKey, region, bucket, domain, protocol, migrate } = req.body

  try {
    // 获取旧配置
    const oldConfig = await SystemConfig.findByPk('storage')
    const oldConfigData = oldConfig ? JSON.parse(oldConfig.value) : null

    // 准备新配置
    const configData = {
      type,
      provider,
      accessKey,
      secretKey,
      region,
      bucket,
      domain,
      protocol: protocol || 'http'
    }

    // 如果存储类型或提供商发生变化，且需要迁移文件
    if (oldConfigData && 
        (oldConfigData.type !== type || 
         (type === 'oss' && oldConfigData.provider !== provider)) && 
        migrate === true) {
      
      // 先测试新的存储配置是否可用
      await storageService.testConnection(configData)

      // 保存新配置
      await SystemConfig.upsert({
        type: 'storage',
        value: JSON.stringify(configData)
      })

      // 更新缓存
      await RedisHelper.set(CACHE_KEY.STORAGE_CONFIG, configData, CACHE_TTL)

      // 开始迁移文件
      await fileService.migrateFiles(oldConfigData, configData)

      res.json({
        code: 0,
        message: '更新成功，文件迁移完成'
      })
    } else {
      // 仅更新配置
      await SystemConfig.upsert({
        type: 'storage',
        value: JSON.stringify(configData)
      })

      // 更新缓存
      await RedisHelper.set(CACHE_KEY.STORAGE_CONFIG, configData, CACHE_TTL)

      res.json({
        code: 0,
        message: '更新成功'
      })
    }
  } catch (error) {
    console.error('更新存储配置失败:', error)
    throw new ApiError(500, '更新存储配置失败: ' + error.message)
  }
}

// 测试存储连接
exports.testStorageConnection = async (req, res) => {
  try {
    const { type, provider, accessKey, secretKey, region, bucket } = req.body

    // 验证必填参数
    if (!type) {
      throw new ApiError(400, '存储类型不能为空')
    }

    if (type === 'local') {
      // 本地存储只需要验证类型
      res.json({
        code: 0,
        message: '本地存储连接正常'
      })
      return
    }

    // 对象存储必填参数验证
    if (!provider) {
      throw new ApiError(400, '服务商不能为空')
    }
    if (!accessKey) {
      throw new ApiError(400, 'AccessKey不能为空')
    }
    if (!secretKey) {
      throw new ApiError(400, 'SecretKey不能为空')
    }
    if (!region) {
      throw new ApiError(400, '区域不能为空')
    }
    if (!bucket) {
      throw new ApiError(400, 'Bucket不能为空')
    }

    // 测试连接
    await storageService.testConnection({
      type,
      provider,
      accessKey,
      secretKey,
      region,
      bucket
    })

    res.json({
      code: 0,
      message: '连接测试成功'
    })
  } catch (error) {
    // 如果是ApiError直接抛出，否则使用通用错误信息
    if (error instanceof ApiError) {
      throw error
    }
    throw new ApiError(400, '存储连接失败')
  }
} 